// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: agent for vbs
// feature: add fast heartbeat feature
// feature: support batch send
// feature: E2E protection
// feature: flowcontroller xml config and writer/reader-resourcelimit
// ------------------------------------------------------------------

#ifndef XMLPARSER_QOS_DATAWRITERQOS_HPP_
#define XMLPARSER_QOS_DATAWRITERQOS_HPP_

#include <xmlparser/attributes/XMLWriterAttributes.h>

#include <xmlparser/qos/XMLQosPolicies.hpp>
#include <xmlparser/qos/XMLWriterQos.hpp>
#include <xmlparser/qos/XMLPublisherQos.hpp>

#include <xmlparser/qos/XMLWriterQos.hpp>
#include <xmlparser/qos/XMLTopicQos.hpp>

namespace vbsutil {
namespace xmlparser {

class RTPSReliableWriterQos {
 public:
    /**
     * @brief Constructor
     */
    RTPS_DllAPI RTPSReliableWriterQos() {}

    /**
     * @brief Destructor
     */
    virtual RTPS_DllAPI ~RTPSReliableWriterQos() = default;

    bool operator==(const RTPSReliableWriterQos& b) const {
        return (this->times == b.times) && (this->disable_positive_acks == b.disable_positive_acks);
    }

    //! Writer Timing Attributes
    WriterTimes times;

    //! Disable positive acks QoS, implemented in the library.
    DisablePositiveACKsQosPolicy disable_positive_acks;

    //! Disable heartbeat piggyback mechanism.
    bool disable_heartbeat_piggyback = false;

    int32_t heartbeat_per_max_samples = 0;
    //When unack sample counts exceeds high_watermark, change to fast heartbeat period.
    int32_t high_watermark = -1;
    //When unack sample counts fall below high_watermark, change to heartbeat period.
    int32_t low_watermark = -1;
};

/**
 * Class DataWriterQos, containing all the possible Qos that can be set for a determined DataWriter.
 * Although these values can be  and are transmitted
 * during the Endpoint Discovery Protocol, not all of the behaviour associated with them has been
 * implemented in the library. Please consult each of them to check for implementation details and
 * default values.
 *
 * @ingroup EDDS_QOS_MODULE
 */
class DataWriterQos : public BaseDataWriterQos {
 public:
    /**
     * @brief Constructor
     */
    RTPS_DllAPI DataWriterQos();

    /**
     * @brief Destructor
     */
    RTPS_DllAPI ~DataWriterQos() = default;

    RTPS_DllAPI bool operator==(const DataWriterQos& b) const {
        return (this->durability_ == b.durability()) && (this->deadline_ == b.deadline()) &&
               (this->liveliness_ == b.liveliness()) && (this->reliability_ == b.reliability()) &&
               (this->history_ == b.history()) && (this->resource_limits_ == b.resource_limits()) &&
               (this->lifespan_ == b.lifespan()) && (this->ownership_ == b.ownership()) &&
               (this->ownership_strength_ == b.ownership_strength()) && (this->publish_mode_ == b.publish_mode()) &&
               (this->properties_ == b.properties()) && (this->reliable_writer_qos_ == b.reliable_writer_qos()) &&
               (this->endpoint_ == b.endpoint()) && (this->writer_resource_limits_ == b.writer_resource_limits()) &&
               (this->e2e_protection_ == b.e2e_protection()) && (this->batch_qos_ == b.batch_qos()) &&
               (ipc_mode_ == b.ipc_mode()) && (agent_flag_ == b.agent_flag());
    }

    void exportDataWriterQosInfo() const;

    RTPS_DllAPI WriterQos get_writerqos(const PublisherQos& pqos) const;

    /**
     * Getter for DeadlineQosPolicy
     *
     * @return DeadlineQosPolicy reference
     */
    RTPS_DllAPI DeadlineQosPolicy& deadline() { return deadline_; }

    /**
     * Getter for DeadlineQosPolicy
     *
     * @return DeadlineQosPolicy reference
     */
    RTPS_DllAPI const DeadlineQosPolicy& deadline() const { return deadline_; }

    /**
     * Setter for DeadlineQosPolicy
     *
     * @param deadline new value for the DeadlineQosPolicy
     */
    RTPS_DllAPI void deadline(const DeadlineQosPolicy& deadline) { deadline_ = deadline; }

    /**
     * Getter for LivelinessQosPolicy
     *
     * @return LivelinessQosPolicy reference
     */
    RTPS_DllAPI LivelinessQosPolicy& liveliness() { return liveliness_; }

    /**
     * Getter for LivelinessQosPolicy
     *
     * @return LivelinessQosPolicy reference
     */
    RTPS_DllAPI const LivelinessQosPolicy& liveliness() const { return liveliness_; }

    /**
     * Setter for LivelinessQosPolicy
     *
     * @param liveliness new value for the LivelinessQosPolicy
     */
    RTPS_DllAPI void liveliness(const LivelinessQosPolicy& liveliness) { liveliness_ = liveliness; }

    /**
     * Getter for HistoryQosPolicy
     *
     * @return HistoryQosPolicy reference
     */
    RTPS_DllAPI HistoryQosPolicy& history() { return history_; }

    /**
     * Getter for HistoryQosPolicy
     *
     * @return HistoryQosPolicy reference
     */
    RTPS_DllAPI const HistoryQosPolicy& history() const { return history_; }

    /**
     * Setter for HistoryQosPolicy
     *
     * @param history new value for the HistoryQosPolicy
     */
    RTPS_DllAPI void history(const HistoryQosPolicy& history) { history_ = history; }

    /**
     * Getter for ResourceLimitsQosPolicy
     *
     * @return ResourceLimitsQosPolicy reference
     */
    RTPS_DllAPI ResourceLimitsQosPolicy& resource_limits() { return resource_limits_; }

    /**
     * Getter for ResourceLimitsQosPolicy
     *
     * @return ResourceLimitsQosPolicy reference
     */
    RTPS_DllAPI const ResourceLimitsQosPolicy& resource_limits() const { return resource_limits_; }

    /**
     * Setter for ResourceLimitsQosPolicy
     *
     * @param resource_limits new value for the ResourceLimitsQosPolicy
     */
    RTPS_DllAPI void resource_limits(const ResourceLimitsQosPolicy& resource_limits) {
        resource_limits_ = resource_limits;
    }

    /**
     * Getter for LifespanQosPolicy
     *
     * @return LifespanQosPolicy reference
     */
    RTPS_DllAPI LifespanQosPolicy& lifespan() { return lifespan_; }

    /**
     * Getter for LifespanQosPolicy
     *
     * @return LifespanQosPolicy reference
     */
    RTPS_DllAPI const LifespanQosPolicy& lifespan() const { return lifespan_; }

    /**
     * Setter for LifespanQosPolicy
     *
     * @param lifespan new value for the LifespanQosPolicy
     */
    RTPS_DllAPI void lifespan(const LifespanQosPolicy& lifespan) { lifespan_ = lifespan; }

    /**
     * Getter for OwnershipQosPolicy
     *
     * @return OwnershipQosPolicy reference
     */
    RTPS_DllAPI OwnershipQosPolicy& ownership() { return ownership_; }

    /**
     * Getter for OwnershipQosPolicy
     *
     * @return OwnershipQosPolicy reference
     */
    RTPS_DllAPI const OwnershipQosPolicy& ownership() const { return ownership_; }

    /**
     * Setter for OwnershipQosPolicy
     *
     * @param ownership new value for the OwnershipQosPolicy
     */
    RTPS_DllAPI void ownership(const OwnershipQosPolicy& ownership) { ownership_ = ownership; }

    /**
     * Getter for OwnershipStrengthQosPolicy
     *
     * @return OwnershipStrengthQosPolicy reference
     */
    RTPS_DllAPI OwnershipStrengthQosPolicy& ownership_strength() { return ownership_strength_; }

    /**
     * Getter for OwnershipStrengthQosPolicy
     *
     * @return OwnershipStrengthQosPolicy reference
     */
    RTPS_DllAPI const OwnershipStrengthQosPolicy& ownership_strength() const { return ownership_strength_; }

    /**
     * Setter for OwnershipStrengthQosPolicy
     *
     * @param ownership_strength new value for the OwnershipStrengthQosPolicy
     */
    RTPS_DllAPI void ownership_strength(const OwnershipStrengthQosPolicy& ownership_strength) {
        ownership_strength_ = ownership_strength;
    }

    /**
     * Getter for PublishModeQosPolicy
     *
     * @return PublishModeQosPolicy reference
     */
    RTPS_DllAPI PublishModeQosPolicy& publish_mode() { return publish_mode_; }

    /**
     * Getter for PublishModeQosPolicy
     *
     * @return PublishModeQosPolicy reference
     */
    RTPS_DllAPI const PublishModeQosPolicy& publish_mode() const { return publish_mode_; }

    /**
     * Setter for PublishModeQosPolicy
     *
     * @param publish_mode new value for the PublishModeQosPolicy
     */
    RTPS_DllAPI void publish_mode(const PublishModeQosPolicy& publish_mode) { publish_mode_ = publish_mode; }

    /**
     * Getter for RTPSReliableWriterQos
     *
     * @return RTPSReliableWriterQos reference
     */
    RTPS_DllAPI RTPSReliableWriterQos& reliable_writer_qos() { return reliable_writer_qos_; }

    /**
     * Getter for RTPSReliableWriterQos
     *
     * @return RTPSReliableWriterQos reference
     */
    RTPS_DllAPI const RTPSReliableWriterQos& reliable_writer_qos() const { return reliable_writer_qos_; }

    /**
     * Setter for RTPSReliableWriterQos
     *
     * @param reliable_writer_qos new value for the RTPSReliableWriterQos
     */
    RTPS_DllAPI void reliable_writer_qos(const RTPSReliableWriterQos& reliable_writer_qos) {
        reliable_writer_qos_ = reliable_writer_qos;
    }

    /**
     * Getter for WriterResourceLimitsQos
     *
     * @return WriterResourceLimitsQos reference
     */
    RTPS_DllAPI WriterResourceLimitsQos& writer_resource_limits() { return writer_resource_limits_; }

    /**
     * Getter for WriterResourceLimitsQos
     *
     * @return WriterResourceLimitsQos reference
     */
    RTPS_DllAPI const WriterResourceLimitsQos& writer_resource_limits() const { return writer_resource_limits_; }

    /**
     * Setter for WriterResourceLimitsQos
     *
     * @param writer_resource_limits new value for the WriterResourceLimitsQos
     */
    RTPS_DllAPI void writer_resource_limits(const WriterResourceLimitsQos& writer_resource_limits) {
        writer_resource_limits_ = writer_resource_limits;
    }

    /**
     * Getter for E2EProtectionQosPolicy
     *
     * @return E2EProtectionQosPolicy reference
     */
    RTPS_DllAPI E2EProtectionQosPolicy& e2e_protection() { return e2e_protection_; }

    /**
     * Getter for E2EProtectionQosPolicy
     *
     * @return E2EProtectionQosPolicy reference
     */
    RTPS_DllAPI const E2EProtectionQosPolicy& e2e_protection() const { return e2e_protection_; }

    /**
     * Setter for E2EProtectionQosPolicy
     *
     * @param e2e_protection new value for the E2EProtectionQosPolicy
     */
    RTPS_DllAPI void e2e_protection(const E2EProtectionQosPolicy& e2e_protection) { e2e_protection_ = e2e_protection; }
    /**
     * Getter for sendMulti
     *
     * @return sendMulti reference
     */
    RTPS_DllAPI const bool& send_multi() const { return send_multi_; }

    /**
     * Setter for sendMulti
     *
     * @param send_multi new value for the sendMulti
     */
    RTPS_DllAPI void send_multi(const bool& send_multi) { send_multi_ = send_multi; }

    /**
     * Getter for BatchQosPolicy
     *
     * @return BatchQosPolicy reference
     */
    RTPS_DllAPI BatchQosPolicy& batch_qos() { return batch_qos_; }

    /**
     * Getter for BatchQosPolicy
     *
     * @return BatchQosPolicy reference
     */
    RTPS_DllAPI const BatchQosPolicy& batch_qos() const { return batch_qos_; }

    /**
     * Setter for BatchQosPolicy
     *
     * @param batch new value for the BatchQosPolicy
     */
    RTPS_DllAPI void batch_qos(const BatchQosPolicy& batch) { batch_qos_ = batch; }

    const uint8_t& ipc_mode() const { return ipc_mode_; }

    void ipc_mode(const uint8_t& ipc_mode) { ipc_mode_ = ipc_mode; }

    const uint8_t& agent_flag() const { return agent_flag_; }

    void agent_flag(const uint8_t& flag) { agent_flag_ = flag; }

 private:
    //! Deadline Qos, implemented in the library.
    DeadlineQosPolicy deadline_;

    //! Liveliness Qos, implemented in the library.
    LivelinessQosPolicy liveliness_;

    //! History Qos, implemented in the library.
    HistoryQosPolicy history_;

    //! Resource Limits Qos, implemented in the library.
    ResourceLimitsQosPolicy resource_limits_;

    //! Lifespan Qos, implemented in the library.
    LifespanQosPolicy lifespan_;

    //! Ownership Qos, implemented in the library.
    OwnershipQosPolicy ownership_;

    //! Ownership Strength Qos, implemented in the library.
    OwnershipStrengthQosPolicy ownership_strength_;

    //! Publication Mode Qos, implemented in the library.
    PublishModeQosPolicy publish_mode_;

    //! RTPS Reliable Writer Qos
    RTPSReliableWriterQos reliable_writer_qos_;

    //! Writer Resource Limits Qos
    WriterResourceLimitsQos writer_resource_limits_;

    //! E2E Protection Qos
    E2EProtectionQosPolicy e2e_protection_;

    BatchQosPolicy batch_qos_;

    //! Whether sending multiple copies is supported
    bool send_multi_ = false;

    uint8_t ipc_mode_ = 0;

    uint8_t agent_flag_ = 0;
};

const DataWriterQos& getDefaultDataWriteQos();

const BatchQosPolicy& getDefaultBatchQos();

}  // namespace xmlparser
}  // namespace vbsutil

#endif  // INCLUDE_EDDS_DDS_PUBLISHER_QOS_DATAWRITERQOS_HPP_
